#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <sys/stat.h> 

#include "util_factory.h"


int path_exists(const char *path) 
{
    struct stat st;
    return stat(path, &st) == 0;
}

int file_size(const char *path) 
{
    struct stat st;
    if(stat(path, &st) == 0)
        return st.st_size;
    else
        return 0;
}


int read_file(char *filepath, void * __restrict data,long offset,size_t size_type,size_t len)
{
    int ret;
    FILE *fd;
    
    fd = fopen(filepath,"rb");
    if (NULL == fd) /* 如果失败了 */
    {
        printf("fopen %s 错误！\n",filepath);
        exit(1); /* 中止程序 */
        return 1;
    }
    if(offset > 0){
        fseek(fd,offset,SEEK_SET);
    }else if(offset == -1){
//        fseek(fd,0,SEEK_CUR);
    }

    ret = fread(data,size_type,len,fd);  
    fclose(fd);
    if(ret < size_type*len){
        printf("read:%d:%d\n",len,ret);
        return 1;
    }
    return 0;
}

int write_file(char *fileName_withPath, void *__restrict data,size_t size_type,size_t len)
{
    int ret;
    FILE *fd;

    fd = fopen(fileName_withPath,"ab+");
    if (NULL == fd) /* 如果失败了 */
    {
        printf("fopen %s 错误！\n",fileName_withPath);
        exit(1); /* 中止程序 */
        return 1;
    }

    ret =fwrite(data,size_type,len,fd);    

    fclose(fd);

    return 0;
}

int get_path_file_name(char *folderPath) 
{
    DIR* dir = opendir(folderPath);
    struct dirent* entry;
 
    if (dir == NULL) {
        printf("Folder not found or error occurred.\n");
        return 1;
    }
 
    while ((entry = readdir(dir)) != NULL) {
        printf("File Name: %s\n", entry->d_name);
    }
 
    closedir(dir);
    return 0;
}

/******************************************************************************************
 * 函数：创建该路径下的文件
 * 输入参数：
 *      filepath 文件路存放的路径，如果没有该路径，创建最后一层文件夹，如果该目录缺少上一层文件夹，创建失败
 *      type：文件类型：0：带时间格式的文件type_num_2024_02_10_090210_123.bin  1:type_num.bin
 *      num: 
 * 输出：
 *      outfileName：带路径的文件名称
 *  
********************************************************************************************/
void creat_file_name(char *filePath,int type,int num,char * outfileName)
{
    char tmp[256];
    memset(tmp,0,sizeof(tmp));

    struct timespec ts;
    struct tm t;
    struct timeval tv;

    if(!path_exists(filePath)){
        mkdir(filePath,0666);
    }
    
    switch (type)
    {
    case 0:
        /* code */
        clock_gettime(CLOCK_REALTIME, &ts);
        gettimeofday(&tv, NULL);
        strftime(tmp, sizeof(tmp), "%Y_%m_%d_%H%M%S", localtime_r(&ts.tv_sec, &t));
        sprintf(outfileName,"%s/%d_%d_%s_%03u.bin",filePath,type,num,tmp,tv.tv_usec/1000); 
        break;
    case 1:
        sprintf(outfileName,"%s/%d_%d.bin",filePath,type,num);
        break;
    default:

        break;
    }
}

/*
*动态库memcpy
*/
int lib_memcpy(void *dst,void *src,size_t size)
{
    int l_u32_block_idx_max;
    int l_u32_less_block_idx_max;
    int l_u32_idex;
    l_u32_block_idx_max = size/SHARE_DDR_BLOCK_SIZE;
    l_u32_less_block_idx_max = size-l_u32_block_idx_max*SHARE_DDR_BLOCK_SIZE;
    for(l_u32_idex=0;l_u32_idex< l_u32_block_idx_max ;l_u32_idex++)
    {
        __memcpy_aarch64_simd(dst,src,SHARE_DDR_BLOCK_SIZE);
        dst += SHARE_DDR_BLOCK_SIZE;
        src += SHARE_DDR_BLOCK_SIZE;
    }

    for(l_u32_idex<0;l_u32_idex<l_u32_less_block_idx_max;l_u32_idex++)
    {
        *((uint8_t *)dst) = *((uint8_t *)src); 
        dst++;
        src++;
    }
    return 0;
}

int thread_uSleep(unsigned int usec) 
{
  pthread_cond_t cond;
  pthread_mutex_t mutex;
  pthread_condattr_t cattr; 
  struct timeval now;
  struct timespec waittime;
  int ret = -1;
  long nsec = 0;
  
  pthread_mutex_init(&mutex, NULL);
  pthread_condattr_init(&cattr);
  pthread_condattr_setclock(&cattr, CLOCK_MONOTONIC);
  pthread_cond_init(&cond, &cattr);
  
  clock_gettime(CLOCK_MONOTONIC, &waittime);
  nsec = waittime.tv_nsec + usec  * 1000; 
  waittime.tv_sec += nsec / 1000000000;
  waittime.tv_nsec = nsec % 1000000000; 
  
  pthread_mutex_lock(&mutex);
  ret = pthread_cond_timedwait(&cond, &mutex, &waittime);
  pthread_mutex_unlock(&mutex);
  return ret;
}

int thread_mSleep(unsigned int msec) 
{
  pthread_cond_t cond;
  pthread_mutex_t mutex;
  pthread_condattr_t cattr; 
  struct timeval now;
  struct timespec waittime;
  int ret = -1;
  long nsec = 0;
  
  pthread_mutex_init(&mutex, NULL);
  pthread_condattr_init(&cattr);
  pthread_condattr_setclock(&cattr, CLOCK_MONOTONIC);
  pthread_cond_init(&cond, &cattr);
  
  clock_gettime(CLOCK_MONOTONIC, &waittime);
  nsec = waittime.tv_nsec + (msec  * 1000)*1000; 
  waittime.tv_sec += nsec / 1000000000;
  waittime.tv_nsec = nsec % 1000000000; 
  
  pthread_mutex_lock(&mutex);
  ret = pthread_cond_timedwait(&cond, &mutex, &waittime);
  pthread_mutex_unlock(&mutex);
  return ret;
}

void nano_usleep(unsigned int uSec)
{
   unsigned int interrupt_cnk = 0;
   struct timespec req = {0};
   req.tv_sec  =  uSec / 1000000;
   req.tv_nsec = uSec * 1000;
    while (nanosleep(&req, &req) < 0 && errno == EINTR)
    {
        if(errno == EINTR)
        {
         interrupt_cnk ++;
        }	
    }
    if(interrupt_cnk > 0)
    {
      printf("uSec[%d]us interruupt_cnk:%d\n",uSec,interrupt_cnk);	
    }
}